/**********************************************************************************
 * Code license:  GNU General Public License v3                                   *
 * Main page:     https://code.google.com/p/library-cross-platform/               *
 * Issue tracker: https://code.google.com/p/library-cross-platform/issues/list    *
***********************************************************************************/

package library.classloader;

import java.lang.reflect.InvocationTargetException;
import java.util.*;

@SuppressWarnings({ "rawtypes", "unchecked" })
public class ClassLoadSingleton extends ClassLoad {
  private          Hashtable          loadedInstances = new Hashtable();
  protected static ClassLoadSingleton thisInstance    = null;

  public ClassLoadSingleton() {
  }
  
  public static ClassLoadSingleton getInstance() {
    if(thisInstance == null) {
      thisInstance = new ClassLoadSingleton();
    }
    return thisInstance;
  }
  
  public void registerClass(String className, Object obj) {
    loadedInstances.put(className, obj);
  }
  
  public void removeClass(String className) {
    loadedInstances.remove(className);
  }
  
  public Object getClass(String className) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, SecurityException {
    Class  cl = null;
    Object obj = null, lobject;
    int index = 1;
    String[] splits = className.split("\\$");
    String objName;

    obj = (Object)loadedInstances.get(splits[0]);
    if(obj == null) {
      cl = loadClass(splits[0]);
      obj = cl.newInstance();
      loadedInstances.put(splits[0], obj);
    }

    if(splits.length == 1)
     return obj;
    
    objName = splits[0];
    while (index < splits.length) {
      objName = objName + "$" + splits[index++];
      lobject = (Object)loadedInstances.get(objName);
      if(lobject != null) {
       obj = lobject;
       continue;
      }
      for (Class<?> cls : obj.getClass().getDeclaredClasses()) {
        if(cls.getName().equals(objName)) {
          obj = getClass(objName, cls, obj);
          loadedInstances.put(objName, obj);
        }
      }
    }
    return obj;
  }
  public Object _getClass(String className) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, SecurityException {
    Object result = (Object)loadedInstances.get(className);
    if(result != null)
     return result;
    else {
     result = super.getClass(className);
     loadedInstances.put(className, result);
    }
    return result;
  }
}
